package com.yjz.jvm.juc.wait_notify_notifyall;

import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.concurrent.CountDownLatch;

/**
 * wait,notify,notifyall
 */
@Slf4j
public class wait_notify_study {

  //利用CountDownLatch  让子线程同时执行(这句话是放屁，同一时刻只能有一个线程在运行，因为只能有一个线程抢占到cpu的时间片)
  private static CountDownLatch latch = new CountDownLatch(1);


  private static Object lock = new Object();

  static Thread th1 = new Thread(() -> {
    synchronized (lock) {
      try {
        latch.await();
        log.info("线程" + Thread.currentThread().getName() + "运行开始运行时间" + System.currentTimeMillis());
        //调用锁对象的wait()方法，释放对象锁，进入等待状态(需要等待其他线程唤醒)
        lock.wait();
        log.info("线程" + Thread.currentThread().getName() + "被唤醒，运行开始运行时间" + System.currentTimeMillis());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      log.info("线程" + Thread.currentThread().getName() + "获得锁");
    }
  }, "线程1");


  static Thread th2 = new Thread(() -> {
    synchronized (lock) {
      log.info("线程" + Thread.currentThread().getName() + "获得锁");
      try {
        latch.await();
        log.info("线程" + Thread.currentThread().getName() + "运行开始运行时间" + System.currentTimeMillis());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      log.info("线程" + Thread.currentThread().getName() + "获得锁");
      //唤醒正在等待lock对象锁的线程
      lock.notify();
      log.info("线程" + Thread.currentThread().getName() + "调用了object.notify()");
    }
    log.info("线程" + Thread.currentThread().getName() + "释放了锁");
    ;
  }, "线程2");

  public static void main(String[] args) throws InterruptedException {
    log.info("主线程开始");
    /*若th2先执行则程序会发生死锁，因为th1里面调用的wait()方法，th1进入对象的等待池了*/
    th1.start();
    Thread.sleep(2000);
    th2.start();
    latch.countDown();
    log.info("主线程结束");
  }

}
